package com.mcp.converter.facade;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mcp.converter.application.service.DatabaseMigrationService;
import com.mcp.converter.application.service.SqlAnalysisService;
import com.mcp.converter.application.service.XmlCompatibilityAnalysisService;
import com.mcp.converter.domain.parser.*;
import com.mcp.converter.shared.response.analysis.*;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * MCP工具门面类
 * 负责将MCP工具调用委托给具体的业务服务
 *
 * @author zengxiong
 */
@Slf4j
@Component
public class McpToolsFacade {
    private final SqlAnalysisService sqlAnalysisService;
    private final DatabaseMigrationService databaseMigrationService;
    private final MybatisXMLParser mybatisXMLParser;
    private final IbatisXMLParser ibatisXMLParser;
    private final IfpXMLParser ifpXMLParser;
    private final XmlCompatibilityAnalysisService xmlCompatibilityAnalysisService;
    private final ObjectMapper objectMapper;

    public McpToolsFacade(SqlAnalysisService sqlAnalysisService, DatabaseMigrationService databaseMigrationService,
                          MybatisXMLParser mybatisXMLParser, IbatisXMLParser ibatisXMLParser, IfpXMLParser ifpXMLParser, XmlCompatibilityAnalysisService xmlCompatibilityAnalysisService) {
        this.sqlAnalysisService = sqlAnalysisService;
        this.databaseMigrationService = databaseMigrationService;
        this.mybatisXMLParser = mybatisXMLParser;
        this.ibatisXMLParser = ibatisXMLParser;
        this.ifpXMLParser = ifpXMLParser;
        this.xmlCompatibilityAnalysisService = xmlCompatibilityAnalysisService;
        this.objectMapper = new ObjectMapper();
    }

    /**
     * 分析Oracle 19c版本的SQL在Oracle模式的V4.2.1版本OceanBase中的兼容性
     */
    @Tool(description = "分析oracle 19c版本的sql在oracle模式的V4.2.1版本oceanbase中的兼容性并提供转换建议及详细报告")
    @Cacheable(value = "sqlAnalysis", key = "#sql")
    public String analyzeSQL(@ToolParam(description = "sql语句") String sql) {
        // 输入验证
        if (sql == null || sql.trim().isEmpty()) {
            return "{\"success\": false, \"error\": \"SQL语句不能为空\"}";
        }

        long startTime = System.currentTimeMillis();

        try {
            // SQL预处理
            String normalizedSql = sql.trim();
            log.info("开始分析SQL，长度: {} 字符", normalizedSql.length());

            // 执行分析
            AnalysisResponse response = sqlAnalysisService.analyze(normalizedSql);

            // 格式化响应
            try {
                java.util.Map<String, Object> result = new java.util.HashMap<>();
                result.put("success", true);
                result.put("compatible", response.isCompatible());
                result.put("reportId", response.getReportId());
                result.put("detailedAnalysis", response.getDetailedAnalysis());
                result.put("conversionSuggestions", response.getConversionSuggestions());
                result.put("incompatibilityDetails", response.getIncompatibilityDetails());
                result.put("criticalIssues", response.getCriticalIssues());
                result.put("timestamp", java.time.LocalDateTime.now().toString());

                return objectMapper.writeValueAsString(result);
            } catch (Exception e) {
                log.error("格式化分析响应失败: {}", e.getMessage(), e);
                return "{\"success\": false, \"error\": \"格式化响应失败: " + e.getMessage() + "\"}";
            }

        } catch (Exception e) {
            long errorTime = System.currentTimeMillis() - startTime;
            log.error("SQL分析失败，耗时: {}ms, 错误: {}", errorTime, e.getMessage(), e);

            return "{\"success\": false, \"error\": \"SQL分析失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * 批量分析SQL
     */
    @Tool(description = "批量分析多个SQL语句的Oracle到OceanBase兼容性")
    public String analyzeSQLBatch(@ToolParam(description = "SQL语句列表") List<String> sqlList) {
        if (sqlList == null || sqlList.isEmpty()) {
            return "{\"success\": false, \"error\": \"SQL列表不能为空\"}";
        }

        long startTime = System.currentTimeMillis();

        try {
            log.info("开始批量分析SQL，数量: {}", sqlList.size());

            // 预处理SQL列表
            List<String> normalizedSqls = new ArrayList<>();
            for (String sql : sqlList) {
                normalizedSqls.add(sql != null ? sql.trim() : "");
            }

            // 执行批量分析
            BatchAnalysisResponse response = sqlAnalysisService.analyzeBatch(normalizedSqls);

            // 格式化响应
            try {
                java.util.Map<String, Object> result = new java.util.HashMap<>();
                result.put("success", true);
                result.put("totalCount", response.getTotalCount());
                result.put("compatibleCount", response.getCompatibleCount());
                result.put("incompatibleCount", response.getIncompatibleCount());
                result.put("errorCount", response.getErrorCount());
                result.put("errors", response.getErrors());
                result.put("timestamp", java.time.LocalDateTime.now().toString());

                return objectMapper.writeValueAsString(result);
            } catch (Exception e) {
                log.error("格式化批量分析响应失败: {}", e.getMessage(), e);
                return "{\"success\": false, \"error\": \"格式化批量响应失败: " + e.getMessage() + "\"}";
            }

        } catch (Exception e) {
            long errorTime = System.currentTimeMillis() - startTime;
            log.error("批量SQL分析失败，耗时: {}ms, 错误: {}", errorTime, e.getMessage(), e);
            return "{\"success\": false, \"error\": \"批量SQL分析失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * 删除OceanBase临时索引
     */
    @Tool(description = "删除OceanBase临时索引，默认自动执行，设置为false可生成SQL文件而不执行")
    public String dropTempIndexes(@ToolParam(description = "数据库连接URL") String oceanbaseUrl,
                                 @ToolParam(description = "数据库用户名") String oceanbaseUsername,
                                 @ToolParam(description = "数据库密码") String oceanbasePassword,
                                 @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始处理OceanBase临时索引，模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.dropTempIndexes(oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("临时索引处理完成");
            return result;
        } catch (Exception e) {
            log.error("处理临时索引失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"处理临时索引失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * Oracle授权迁移
     */
    @Tool(description = "oracle授权迁移, 默认自动执行，设置为false可生成SQL文件而不执行")
    public String syncGrant(@ToolParam(description = "oracle数据库连接URL") String oracleUrl,
                           @ToolParam(description = "oracle数据库用户名") String oracleUserName,
                           @ToolParam(description = "oracle数据库密码") String oraclePassword,
                           @ToolParam(description = "oracle数据表所属owner") String oracleTableOwner,
                           @ToolParam(description = "oceanbase数据库连接URL") String oceanbaseUrl,
                           @ToolParam(description = "oceanbase数据库用户名") String oceanbaseUsername,
                           @ToolParam(description = "oceanbase数据库密码") String oceanbasePassword,
                           @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始Oracle授权迁移, 模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.syncGrant(oracleUrl, oracleUserName, oraclePassword,
                    oracleTableOwner, oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("授权迁移完成");
            return result;
        } catch (Exception e) {
            log.error("授权迁移失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"授权迁移失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * Oracle序列迁移
     */
    @Tool(description = "oracle序列迁移, 默认自动执行，设置为false可生成SQL文件而不执行")
    public String syncSequence(@ToolParam(description = "oracle数据库连接URL") String oracleUrl,
                              @ToolParam(description = "oracle数据库用户名") String oracleUserName,
                              @ToolParam(description = "oracle数据库密码") String oraclePassword,
                              @ToolParam(description = "oracle序列所属owner") String oracleSeqOwner,
                              @ToolParam(description = "oceanbase数据库连接URL") String oceanbaseUrl,
                              @ToolParam(description = "oceanbase数据库用户名") String oceanbaseUsername,
                              @ToolParam(description = "oceanbase数据库密码") String oceanbasePassword,
                              @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始Oracle序列迁移, 模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.syncSequence(oracleUrl, oracleUserName, oraclePassword,
                    oracleSeqOwner, oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("序列迁移完成");
            return result;
        } catch (Exception e) {
            log.error("序列迁移失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"序列迁移失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * Oracle同义词迁移
     */
    @Tool(description = "oracle同义词迁移, 默认自动执行，设置为false可生成SQL文件而不执行")
    public String syncPublicSynonym(@ToolParam(description = "oracle数据库连接URL") String oracleUrl,
                                   @ToolParam(description = "oracle数据库用户名") String oracleUserName,
                                   @ToolParam(description = "oracle数据库密码") String oraclePassword,
                                   @ToolParam(description = "oracle表所属owner") String oracleTableOwner,
                                   @ToolParam(description = "oceanbase数据库连接URL") String oceanbaseUrl,
                                   @ToolParam(description = "oceanbase数据库用户名") String oceanbaseUsername,
                                   @ToolParam(description = "oceanbase数据库密码") String oceanbasePassword,
                                   @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始Oracle同义词迁移, 模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.syncPublicSynonym(oracleUrl, oracleUserName, oraclePassword,
                    oracleTableOwner, oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("同义词迁移完成");
            return result;
        } catch (Exception e) {
            log.error("同义词迁移失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"同义词迁移失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * Oracle存储过程迁移
     */
    @Tool(description = "oracle存储过程迁移, 默认自动执行，设置为false可生成SQL文件而不执行")
    public String syncProcedure(@ToolParam(description = "oracle数据库连接URL") String oracleUrl,
                               @ToolParam(description = "oracle数据库用户名") String oracleUserName,
                               @ToolParam(description = "oracle数据库密码") String oraclePassword,
                               @ToolParam(description = "oracle存储过程所属owner") String oracleProcedureOwner,
                               @ToolParam(description = "oceanbase数据库连接URL") String oceanbaseUrl,
                               @ToolParam(description = "oceanbase数据库用户名") String oceanbaseUsername,
                               @ToolParam(description = "oceanbase数据库密码") String oceanbasePassword,
                               @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始Oracle存储过程迁移, 模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.syncProcedure(oracleUrl, oracleUserName, oraclePassword,
                    oracleProcedureOwner, oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("存储过程迁移完成");
            return result;
        } catch (Exception e) {
            log.error("存储过程迁移失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"存储过程迁移失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * Oracle函数迁移
     */
    @Tool(description = "oracle函数迁移, 默认自动执行，设置为false可生成SQL文件而不执行")
    public String syncFunction(@ToolParam(description = "oracle数据库连接URL") String oracleUrl,
                              @ToolParam(description = "oracle数据库用户名") String oracleUserName,
                              @ToolParam(description = "oracle数据库密码") String oraclePassword,
                              @ToolParam(description = "oracle函数所属owner") String oracleFunctionOwner,
                              @ToolParam(description = "oceanbase数据库连接URL") String oceanbaseUrl,
                              @ToolParam(description = "oceanbase数据库用户名") String oceanbaseUsername,
                              @ToolParam(description = "oceanbase数据库密码") String oceanbasePassword,
                              @ToolParam(description = "是否自动执行，默认true") boolean isAutoExecute) {
        try {
            log.info("开始Oracle函数迁移, 模式: {}", isAutoExecute ? "自动执行" : "手动生成SQL文件");
            String result = databaseMigrationService.syncFunction(oracleUrl, oracleUserName, oraclePassword,
                    oracleFunctionOwner, oceanbaseUrl, oceanbaseUsername, oceanbasePassword, isAutoExecute);
            log.info("函数迁移完成");
            return result;
        } catch (Exception e) {
            log.error("函数迁移失败: {}", e.getMessage(), e);
            return "{\"success\": false, \"error\": \"函数迁移失败: " + e.getMessage() + "\"}";
        }
    }

    /**
     * 分析XML兼容性 - 支持MyBatis和iBatis框架
     */
    @Tool(description = "分析指定XML文件的Oracle到OceanBase兼容性，自动提取完整SQL语句并进行批量兼容性检测，支持MyBatis和iBatis框架")
    public String analyzeXMLCompatibility(@ToolParam(description = "XML文件路径") String xmlFilePath,
                                         @ToolParam(description = "是否为iBatis框架的XML文件，默认false(MyBatis)") boolean isIbatis) {
        try {
            log.info("开始分析XML兼容性: {}, 框架类型: {}", xmlFilePath, isIbatis ? "iBatis" : "MyBatis");

            // 1. 根据框架类型选择对应的解析器进行SQL提取
            String extractResult;
            String fileName;
            
            if (isIbatis) {
                // 使用iBatis解析器
                extractResult = ibatisXMLParser.extractSQLsFromXML(xmlFilePath);
                fileName = ibatisXMLParser.extractFileNameFromPath(xmlFilePath);
            } else {
                // 使用MyBatis解析器
                extractResult = mybatisXMLParser.extractSQLsFromXML(xmlFilePath);
                fileName = mybatisXMLParser.extractFileNameFromPath(xmlFilePath);
            }

            // 2. 解析提取结果
            ObjectMapper mapper = new ObjectMapper();
            JsonNode extractNode = mapper.readTree(extractResult);

            if (!extractNode.get("success").asBoolean()) {
                return String.format("{\"success\": false, \"error\": \"SQL提取失败\", \"filename\": \"%s\", \"framework\": \"%s\", \"details\": \"%s\", \"timestamp\": \"%s\"}",
                        fileName,
                        isIbatis ? "iBatis" : "MyBatis",
                        extractNode.get("errorMessage").asText(),
                        LocalDateTime.now());
            }

            // 3. 过滤出完整的SQL语句（排除片段）
            List<String> validSqls = new ArrayList<>();
            List<JsonNode> sqlDetailsList = new ArrayList<>();
            JsonNode sqlStatements = extractNode.get("sqlStatements");

            Set<String> skipPatterns;
            if (isIbatis) {
                // iBatis框架的SQL片段标识符，iBatis特有的片段标识
                skipPatterns = Set.of(
                        "Base_Column_List", "Example_Where_Clause", "Update_By_Example_Where_Clause",
                        "sql", "include"
                );
            } else {
                // MyBatis框架的SQL片段标识符
                skipPatterns = Set.of(
                        "Base_Column_List", "Example_Where_Clause", "Update_By_Example_Where_Clause"
                );
            }

            for (JsonNode sqlNode : sqlStatements) {
                String sqlId = sqlNode.get("sqlId").asText();
                boolean isComplete = sqlNode.get("isComplete").asBoolean();

                // 跳过SQL片段
                boolean shouldSkip = skipPatterns.stream().anyMatch(pattern -> sqlId.contains(pattern));

                if (shouldSkip) {
                    // 构建跳过的SQL详情
                    ObjectNode detailNode = mapper.createObjectNode();
                    detailNode.put("sqlId", sqlId);
                    detailNode.put("elementType", sqlNode.get("elementType").asText());
                    detailNode.put("isComplete", false);
                    detailNode.put("willAnalyze", false);
                    detailNode.put("skipReason", "SQL片段，不进行兼容性分析");
                    detailNode.put("originalSql", sqlNode.get("originalSql").asText());
                    detailNode.put("fixedSql", "");
                    detailNode.put("startLine", sqlNode.get("startLine").asInt());
                    detailNode.put("endLine", sqlNode.get("endLine").asInt());
                    sqlDetailsList.add(detailNode);
                    continue;
                }

                if (isComplete) {
                    String fixedSql = sqlNode.get("fixedSql").asText();
                    validSqls.add(fixedSql);

                    // 构建将要分析的SQL详情
                    ObjectNode detailNode = mapper.createObjectNode();
                    detailNode.put("sqlId", sqlId);
                    detailNode.put("elementType", sqlNode.get("elementType").asText());
                    detailNode.put("isComplete", true);
                    detailNode.put("willAnalyze", true);
                    detailNode.put("originalSql", sqlNode.get("originalSql").asText());
                    detailNode.put("fixedSql", fixedSql);
                    detailNode.put("startLine", sqlNode.get("startLine").asInt());
                    detailNode.put("endLine", sqlNode.get("endLine").asInt());
                    sqlDetailsList.add(detailNode);
                } else {
                    // 不完整的SQL也记录但不分析
                    ObjectNode detailNode = mapper.createObjectNode();
                    detailNode.put("sqlId", sqlId);
                    detailNode.put("elementType", sqlNode.get("elementType").asText());
                    detailNode.put("isComplete", false);
                    detailNode.put("willAnalyze", false);
                    detailNode.put("skipReason", "SQL语句不完整");
                    detailNode.put("originalSql", sqlNode.get("originalSql").asText());
                    detailNode.put("fixedSql", sqlNode.get("fixedSql").asText());
                    detailNode.put("startLine", sqlNode.get("startLine").asInt());
                    detailNode.put("endLine", sqlNode.get("endLine").asInt());
                    sqlDetailsList.add(detailNode);
                }
            }

            // 4. 批量兼容性分析
            BatchAnalysisResponse batchResult;
            if (!validSqls.isEmpty()) {
                batchResult = sqlAnalysisService.analyzeBatch(validSqls);
            } else {
                // 创建空的批量分析结果
                batchResult = new BatchAnalysisResponse();
                batchResult.setTotalCount(0);
            }

            // 5. 根据框架类型执行增强兼容性检测
            FallbackCompatibilityResult fallbackResult;
            CompatibilityReclassificationResult reclassificationResult;
            
            if (isIbatis) {
                // 使用iBatis解析器的兼容性检测方法
                fallbackResult = ibatisXMLParser.performFallbackCompatibilityCheck(validSqls, batchResult);
                reclassificationResult = ibatisXMLParser.performIntelligentReclassification(batchResult, validSqls);
            } else {
                // 使用MyBatis解析器的兼容性检测方法
                fallbackResult = mybatisXMLParser.performFallbackCompatibilityCheck(validSqls, batchResult);
                reclassificationResult = mybatisXMLParser.performIntelligentReclassification(batchResult, validSqls);
            }

            // 6. 构建响应
            int totalSqlCount = sqlStatements.size();
            int validSqlCount = validSqls.size();

            // 计算兼容性百分比（使用修正后的统计，避免重复计算）
            // 直接使用批量分析的结果，避免重复计数
            int finalIncompatibleCount = batchResult.getIncompatibleCount();
            int finalErrorCount = reclassificationResult.correctedErrorCount();
            int finalCompatibleCount = validSqlCount - finalIncompatibleCount - finalErrorCount;
            
            double compatibilityPercentage = validSqlCount > 0 ?
                    ((double) finalCompatibleCount / validSqlCount) * 100.0 : 100.0;

            ObjectNode response = mapper.createObjectNode();
            response.put("success", true);
            response.put("fileName", fileName);
            response.put("framework", isIbatis ? "iBatis" : "MyBatis");
            
            // 根据框架类型设置不同的标识字段
            if (isIbatis) {
                response.put("businessLogicId", extractNode.has("businessLogicId") ? extractNode.get("businessLogicId").asText() : "");
            } else {
                response.put("namespace", extractNode.has("namespace") ? extractNode.get("namespace").asText() : "");
            }
            
            response.put("totalSqlCount", totalSqlCount);
            response.put("validSqlCount", validSqlCount);
            response.put("compatibilityPercentage", Math.round(compatibilityPercentage * 100.0) / 100.0);
            response.put("hasCompatibilityAnalysis", validSqlCount > 0);

            // 批量分析结果（使用修正后的统计）
            ObjectNode batchAnalysisNode = mapper.createObjectNode();
            batchAnalysisNode.put("totalCount", batchResult.getTotalCount());
            batchAnalysisNode.put("compatibleCount", batchResult.getCompatibleCount());
            batchAnalysisNode.put("incompatibleCount", finalIncompatibleCount);
            batchAnalysisNode.put("errorCount", reclassificationResult.correctedErrorCount());

            // 构建修正后的错误列表（只保留真正的错误）
            ObjectNode correctedErrorsNode = mapper.createObjectNode();
            if (batchResult.getErrors() != null) {
                for (Map.Entry<Integer, String> errorEntry : batchResult.getErrors().entrySet()) {
                    int sqlIndex = errorEntry.getKey();
                    String errorMessage = errorEntry.getValue();

                    // 根据框架类型检查不兼容函数
                    int actualSqlIndex = sqlIndex < validSqls.size() ? sqlIndex : sqlIndex - 1;
                    if (actualSqlIndex >= 0 && actualSqlIndex < validSqls.size()) {
                        String sql = validSqls.get(actualSqlIndex);
                        boolean containsIncompatible;
                        
                        if (isIbatis) {
                            // 对于iBatis，可能需要不同的不兼容函数检查逻辑
                            // 这里暂时使用MyBatis的检查方法，实际应该在iBatis解析器中实现专门的方法
                            containsIncompatible = mybatisXMLParser.containsIncompatibleFunctions(sql);
                        } else {
                            containsIncompatible = mybatisXMLParser.containsIncompatibleFunctions(sql);
                        }
                        
                        if (!containsIncompatible) {
                            correctedErrorsNode.put(String.valueOf(sqlIndex), errorMessage);
                        }
                    } else {
                        correctedErrorsNode.put(String.valueOf(sqlIndex), errorMessage);
                    }
                }
            }
            batchAnalysisNode.set("errors", correctedErrorsNode);

            // 添加重分类信息
            ObjectNode reclassificationInfo = mapper.createObjectNode();
            reclassificationInfo.put("originalErrorCount", reclassificationResult.originalErrorCount());
            reclassificationInfo.put("reclassifiedAsIncompatible", reclassificationResult.correctedIncompatibleCount() - batchResult.getIncompatibleCount());
            reclassificationInfo.put("finalErrorCount", reclassificationResult.correctedErrorCount());
            batchAnalysisNode.set("reclassificationInfo", reclassificationInfo);

            // 添加后备检测的不兼容函数信息
            if (fallbackResult.getIncompatibleSqlIndexes() != null && !fallbackResult.getIncompatibleSqlIndexes().isEmpty()) {
                ObjectNode incompatibilitiesNode = mapper.createObjectNode();
                fallbackResult.getFunctionDetails().forEach(incompatibilitiesNode::put);
                batchAnalysisNode.set("additionalIncompatibilities", incompatibilitiesNode);
            }

            response.set("batchAnalysis", batchAnalysisNode);

            // SQL详情
            ArrayNode sqlDetailsArray = mapper.createArrayNode();
            sqlDetailsList.forEach(sqlDetailsArray::add);
            response.set("sqlDetails", sqlDetailsArray);

            // 摘要信息（使用修正后的统计）
            String summary = String.format(
                    "%s框架XML文件 %s 兼容性分析完成： 总SQL语句 %d 个， 有效SQL %d 个， 兼容 %d 个， 不兼容 %d 个，分析错误 %d 个",
                    isIbatis ? "iBatis" : "MyBatis", fileName, totalSqlCount, validSqlCount,
                    batchResult.getCompatibleCount(), finalIncompatibleCount, reclassificationResult.correctedErrorCount()
            );
            response.put("summary", summary);

            response.put("timestamp", LocalDateTime.now().toString());

            String result = mapper.writeValueAsString(response);
            log.info("{}框架XML兼容性分析完成: {}", isIbatis ? "iBatis" : "MyBatis", fileName);
            return result;

        } catch (Exception e) {
            log.error("XML兼容性分析失败: {}, 框架: {}", xmlFilePath, isIbatis ? "iBatis" : "MyBatis", e);
            String fileName = isIbatis ? ibatisXMLParser.extractFileNameFromPath(xmlFilePath) : mybatisXMLParser.extractFileNameFromPath(xmlFilePath);
            return String.format("{\"success\": false, \"error\": \"分析过程中发生错误\", \"filename\": \"%s\", \"framework\": \"%s\", \"details\": \"%s\", \"timestamp\": \"%s\"}", 
                fileName, isIbatis ? "iBatis" : "MyBatis", e.getMessage(), LocalDateTime.now());
        }
    }

    /**
     * 批量分析指定目录下的XML文件兼容性 - 支持MyBatis和iBatis框架
     */
    @Tool(description = "分析指定目录下所有XML文件的Oracle到OceanBase兼容性，支持MyBatis和iBatis框架，支持递归扫描子目录，提供详细的兼容性报告")
    public String analyzeDirectoryXMLCompatibility(@ToolParam(description = "目录路径") String directoryPath,
                                                   @ToolParam(description = "是否递归扫描子目录，默认true") boolean recursive,
                                                   @ToolParam(description = "是否为iBatis框架的XML文件，默认false(MyBatis)") boolean isIbatis) {
        long startTime = System.currentTimeMillis();

        try {
            log.info("开始批量分析目录XML兼容性: {}, 递归: {}, 框架: {}", directoryPath, recursive, isIbatis ? "iBatis" : "MyBatis");

            // 1. 根据框架类型扫描XML文件
            List<String> xmlFiles;
            if (isIbatis) {
                xmlFiles = ibatisXMLParser.scanXmlFiles(directoryPath, recursive);
            } else {
                xmlFiles = mybatisXMLParser.scanXmlFiles(directoryPath, recursive);
            }

            if (xmlFiles.isEmpty()) {
                String errorResponse = isIbatis ? 
                    ibatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime, "目录中未找到iBatis XML文件") :
                    mybatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime, "目录中未找到MyBatis XML文件");
                return errorResponse;
            }

            // 2. 批量分析所有XML文件
            List<Map<String, Object>> fileResults = new ArrayList<>();
            List<Map<String, Object>> failedFiles = new ArrayList<>();

            int totalCompatibleCount = 0;
            int totalIncompatibleCount = 0;
            int totalErrorCount = 0;
            int totalSqlCount = 0;
            int totalValidSqlCount = 0;

            for (String xmlFile : xmlFiles) {
                try {
                    log.info("分析{}框架XML文件: {}", isIbatis ? "iBatis" : "MyBatis", xmlFile);
                    // 调用支持框架选择的单文件兼容性分析方法
                    String singleResult = analyzeXMLCompatibility(xmlFile, isIbatis);

                    // 解析单个文件的分析结果
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode resultNode = mapper.readTree(singleResult);

                    if (resultNode.get("success").asBoolean()) {
                        // 分析成功的文件 - 使用修正后的统计数据
                        if (resultNode.has("correctedCompatibleCount")) {
                            totalCompatibleCount += resultNode.get("correctedCompatibleCount").asInt();
                        }
                        if (resultNode.has("correctedIncompatibleCount")) {
                            totalIncompatibleCount += resultNode.get("correctedIncompatibleCount").asInt();
                        }
                        if (resultNode.has("correctedErrorCount")) {
                            totalErrorCount += resultNode.get("correctedErrorCount").asInt();
                        }
                        
                        // 保留batchAnalysis作为备用
                        JsonNode batchAnalysis = resultNode.get("batchAnalysis");
                        if (batchAnalysis != null && !resultNode.has("correctedCompatibleCount")) {
                            totalCompatibleCount += batchAnalysis.get("compatibleCount").asInt();
                            totalIncompatibleCount += batchAnalysis.get("incompatibleCount").asInt();
                            totalErrorCount += batchAnalysis.get("errorCount").asInt();
                        }

                        totalSqlCount += resultNode.get("totalSqlCount").asInt();
                        totalValidSqlCount += resultNode.get("validSqlCount").asInt();

                        // 构建文件结果摘要
                        Map<String, Object> fileSummary = new HashMap<>();
                        fileSummary.put("filePath", xmlFile);
                        
                        String fileName = isIbatis ? 
                            ibatisXMLParser.extractFileNameFromPath(xmlFile) : 
                            mybatisXMLParser.extractFileNameFromPath(xmlFile);
                        fileSummary.put("fileName", fileName);
                        
                        // 根据框架类型设置不同的标识字段
                        if (isIbatis) {
                            fileSummary.put("businessLogicId", resultNode.has("businessLogicId") ? resultNode.get("businessLogicId").asText() : "");
                        } else {
                            fileSummary.put("namespace", resultNode.has("namespace") ? resultNode.get("namespace").asText() : "");
                        }
                        
                        fileSummary.put("framework", isIbatis ? "iBatis" : "MyBatis");
                        fileSummary.put("totalSqlCount", resultNode.get("totalSqlCount").asInt());
                        fileSummary.put("validSqlCount", resultNode.get("validSqlCount").asInt());
                        fileSummary.put("compatibilityPercentage", resultNode.get("compatibilityPercentage").asDouble());

                        // 转换batchAnalysis为Map
                        Map<String, Object> batchAnalysisMap = objectMapper.convertValue(batchAnalysis, Map.class);
                        fileSummary.put("batchAnalysis", batchAnalysisMap);

                        // 检查是否有兼容性问题
                        boolean hasIssues = (batchAnalysis != null &&
                            (batchAnalysis.get("incompatibleCount").asInt() > 0 ||
                             batchAnalysis.get("errorCount").asInt() > 0));
                        fileSummary.put("hasIncompatibilityIssues", hasIssues);

                        fileResults.add(fileSummary);

                    } else {
                        // 分析失败的文件
                        Map<String, Object> failedFile = new HashMap<>();
                        failedFile.put("filePath", xmlFile);
                        
                        String fileName = isIbatis ? 
                            ibatisXMLParser.extractFileNameFromPath(xmlFile) : 
                            mybatisXMLParser.extractFileNameFromPath(xmlFile);
                        failedFile.put("fileName", fileName);
                        failedFile.put("framework", isIbatis ? "iBatis" : "MyBatis");
                        failedFile.put("error", resultNode.get("error").asText());
                        if (resultNode.has("details")) {
                            failedFile.put("details", resultNode.get("details").asText());
                        }

                        failedFiles.add(failedFile);
                    }

                } catch (Exception e) {
                    log.error("分析{}框架XML文件失败: {}", isIbatis ? "iBatis" : "MyBatis", xmlFile, e);
                    Map<String, Object> failedFile = new HashMap<>();
                    failedFile.put("filePath", xmlFile);
                    
                    String fileName = isIbatis ? 
                        ibatisXMLParser.extractFileNameFromPath(xmlFile) : 
                        mybatisXMLParser.extractFileNameFromPath(xmlFile);
                    failedFile.put("fileName", fileName);
                    failedFile.put("framework", isIbatis ? "iBatis" : "MyBatis");
                    failedFile.put("error", "分析过程中发生异常");
                    failedFile.put("details", e.getMessage());

                    failedFiles.add(failedFile);
                }
            }

            // 3. 构建汇总报告
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("directoryPath", directoryPath);
            response.put("recursive", recursive);
            response.put("framework", isIbatis ? "iBatis" : "MyBatis");
            response.put("timestamp", LocalDateTime.now().toString());
            response.put("analyzeDuration", System.currentTimeMillis() - startTime);

            // 文件统计
            Map<String, Object> fileStats = new HashMap<>();
            fileStats.put("totalXmlFiles", xmlFiles.size());
            fileStats.put("successfullyAnalyzed", fileResults.size());
            fileStats.put("failed", failedFiles.size());
            response.put("fileStatistics", fileStats);

            // 兼容性统计
            if (!fileResults.isEmpty()) {
                Map<String, Object> compatibilityStats = new HashMap<>();
                compatibilityStats.put("totalSqlStatements", totalSqlCount);
                compatibilityStats.put("totalValidSqlStatements", totalValidSqlCount);
                compatibilityStats.put("compatibleSql", totalCompatibleCount);
                compatibilityStats.put("incompatibleSql", totalIncompatibleCount);
                compatibilityStats.put("errorSql", totalErrorCount);

                double overallCompatibility = totalValidSqlCount > 0 ?
                    ((double) totalCompatibleCount / totalValidSqlCount) * 100 : 100.0;
                compatibilityStats.put("overallCompatibilityPercentage",
                    Math.round(overallCompatibility * 100.0) / 100.0);

                response.put("compatibilityStatistics", compatibilityStats);
            }

            // 详细文件结果
            response.put("fileResults", fileResults);

            // 失败文件列表
            if (!failedFiles.isEmpty()) {
                response.put("failedFiles", failedFiles);
            }

            // 生成汇总信息
            String summary = String.format(
                "目录 %s %s框架兼容性分析完成：扫描了 %d 个XML文件，成功分析 %d 个，失败 %d 个。" +
                "总计SQL语句 %d 条，有效SQL %d 条，兼容 %d 条，不兼容 %d 条，错误 %d 条。",
                directoryPath, isIbatis ? "iBatis" : "MyBatis", xmlFiles.size(), fileResults.size(), failedFiles.size(),
                totalSqlCount, totalValidSqlCount, totalCompatibleCount,
                totalIncompatibleCount, totalErrorCount
            );
            response.put("summary", summary);

            String result = objectMapper.writeValueAsString(response);
            log.info("目录{}框架XML兼容性分析完成: {}", isIbatis ? "iBatis" : "MyBatis", directoryPath);
            return result;

        } catch (Exception e) {
            log.error("目录{}框架XML兼容性分析失败: {}", isIbatis ? "iBatis" : "MyBatis", directoryPath, e);
            String errorResponse = isIbatis ? 
                ibatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime,
                    "iBatis框架目录分析过程中发生异常: " + e.getMessage()) :
                mybatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime,
                    "MyBatis框架目录分析过程中发生异常: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 分析ifp框架XML文件的Oracle到OceanBase兼容性
     */
    @Tool(description = "分析ifp框架指定XML文件的Oracle到OceanBase兼容性，自动提取完整SQL语句并进行批量兼容性检测")
    public String analyzeIfpXMLCompatibility(@ToolParam(description = "ifp框架XML文件路径") String xmlFilePath) {
        long startTime = System.currentTimeMillis();

        try {
            log.info("开始分析ifp框架XML兼容性: {}", xmlFilePath);

            // 1. 输入验证
            String validationError = xmlCompatibilityAnalysisService.validateInput(xmlFilePath, startTime);
            if (validationError != null) {
                return validationError;
            }

            // 2. 提取和解析SQL
            ObjectMapper mapper = new ObjectMapper();
            IfpAnalysisContext context = xmlCompatibilityAnalysisService.extractAndParseSqls(xmlFilePath, mapper, startTime);
            if (context.hasError()) {
                return context.getErrorResponse();
            }
            
            // 3. 执行兼容性分析
            CompatibilityAnalysisResult analysisResult = xmlCompatibilityAnalysisService.performCompatibilityAnalysis(context.getValidSqls());
            
            // 4. 构建并返回响应
            return xmlCompatibilityAnalysisService.buildIfpCompatibilityResponse(context, analysisResult, mapper);
            
        } catch (JsonProcessingException e) {
            log.error("JSON处理异常: {}", xmlFilePath, e);
            return xmlCompatibilityAnalysisService.buildJsonErrorResponse(xmlFilePath, e);
        } catch (Exception e) {
            log.error("ifp框架XML兼容性分析失败: {}", xmlFilePath, e);
            return xmlCompatibilityAnalysisService.buildGenericErrorResponse(xmlFilePath, e);
        }
    }

    /**
     * 批量分析指定目录下的ifp框架XML文件兼容性
     */
    @Tool(description = "分析指定目录下所有ifp框架XML文件的Oracle到OceanBase兼容性，支持递归扫描子目录，提供详细的兼容性报告")
    public String analyzeDirectoryIfpXMLCompatibility(@ToolParam(description = "目录路径") String directoryPath,
                                                     @ToolParam(description = "是否递归扫描子目录，默认true") boolean recursive) {
        long startTime = System.currentTimeMillis();

        try {
            log.info("开始批量分析目录ifp框架XML兼容性: {}, 递归: {}", directoryPath, recursive);

            // 1. 扫描XML文件
            List<String> xmlFiles = ifpXMLParser.scanXmlFiles(directoryPath, recursive);

            if (xmlFiles.isEmpty()) {
                return mybatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime,
                        "目录中未找到ifp框架XML文件");
            }

            // 2. 批量分析所有XML文件
            List<Map<String, Object>> fileResults = new ArrayList<>();
            List<Map<String, Object>> failedFiles = new ArrayList<>();

            int totalCompatibleCount = 0;
            int totalIncompatibleCount = 0;
            int totalErrorCount = 0;
            int totalSqlCount = 0;
            int totalValidSqlCount = 0;

            for (String xmlFile : xmlFiles) {
                try {
                    log.info("分析ifp框架XML文件: {}", xmlFile);
                    // 调用现有的单文件ifp兼容性分析方法
                    String singleResult = analyzeIfpXMLCompatibility(xmlFile);

                    // 解析单个文件的分析结果
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode resultNode = mapper.readTree(singleResult);

                    if (resultNode.get("success").asBoolean()) {
                        // 分析成功的文件
                        JsonNode batchAnalysis = resultNode.get("batchAnalysis");
                        if (batchAnalysis != null) {
                            // 优先使用修正后的统计数据
                            if (resultNode.has("correctedCompatibleCount") && 
                                resultNode.has("correctedIncompatibleCount") && 
                                resultNode.has("correctedErrorCount")) {
                                totalCompatibleCount += resultNode.get("correctedCompatibleCount").asInt();
                                totalIncompatibleCount += resultNode.get("correctedIncompatibleCount").asInt();
                                totalErrorCount += resultNode.get("correctedErrorCount").asInt();
                            } else {
                                // 回退到原始统计数据
                                totalCompatibleCount += batchAnalysis.get("compatibleCount").asInt();
                                totalIncompatibleCount += batchAnalysis.get("incompatibleCount").asInt();
                                totalErrorCount += batchAnalysis.get("errorCount").asInt();
                            }
                        }

                        totalSqlCount += resultNode.get("totalSqlCount").asInt();
                        totalValidSqlCount += resultNode.get("validSqlCount").asInt();

                        // 构建文件结果摘要
                        Map<String, Object> fileSummary = new HashMap<>();
                        fileSummary.put("filePath", xmlFile);
                        fileSummary.put("fileName", mybatisXMLParser.extractFileNameFromPath(xmlFile));
                        fileSummary.put("businessLogicId", resultNode.has("businessLogicId") ? resultNode.get("businessLogicId").asText() : "");
                        fileSummary.put("totalSqlCount", resultNode.get("totalSqlCount").asInt());
                        fileSummary.put("validSqlCount", resultNode.get("validSqlCount").asInt());
                        fileSummary.put("compatibilityPercentage", resultNode.get("compatibilityPercentage").asDouble());

                        // 转换batchAnalysis为Map
                        Map<String, Object> batchAnalysisMap = objectMapper.convertValue(batchAnalysis, Map.class);
                        fileSummary.put("batchAnalysis", batchAnalysisMap);

                        // 检查是否有兼容性问题
                        boolean hasIssues = (batchAnalysis != null &&
                            (batchAnalysis.get("incompatibleCount").asInt() > 0 ||
                             batchAnalysis.get("errorCount").asInt() > 0));
                        fileSummary.put("hasIncompatibilityIssues", hasIssues);

                        fileResults.add(fileSummary);

                    } else {
                        // 分析失败的文件
                        Map<String, Object> failedFile = new HashMap<>();
                        failedFile.put("filePath", xmlFile);
                        failedFile.put("fileName", mybatisXMLParser.extractFileNameFromPath(xmlFile));
                        failedFile.put("error", resultNode.get("error").asText());
                        if (resultNode.has("details")) {
                            failedFile.put("details", resultNode.get("details").asText());
                        }

                        failedFiles.add(failedFile);
                    }

                } catch (Exception e) {
                    log.error("分析ifp框架XML文件失败: {}", xmlFile, e);
                    Map<String, Object> failedFile = new HashMap<>();
                    failedFile.put("filePath", xmlFile);
                    failedFile.put("fileName", mybatisXMLParser.extractFileNameFromPath(xmlFile));
                    failedFile.put("error", "分析过程中发生异常");
                    failedFile.put("details", e.getMessage());

                    failedFiles.add(failedFile);
                }
            }

            // 3. 构建汇总报告
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("directoryPath", directoryPath);
            response.put("recursive", recursive);
            response.put("timestamp", LocalDateTime.now().toString());
            response.put("analyzeDuration", System.currentTimeMillis() - startTime);
            response.put("frameworkType", "ifp");

            // 文件统计
            Map<String, Object> fileStats = new HashMap<>();
            fileStats.put("totalXmlFiles", xmlFiles.size());
            fileStats.put("successfullyAnalyzed", fileResults.size());
            fileStats.put("failed", failedFiles.size());
            response.put("fileStatistics", fileStats);

            // 兼容性统计
            if (!fileResults.isEmpty()) {
                Map<String, Object> compatibilityStats = new HashMap<>();
                compatibilityStats.put("totalSqlStatements", totalSqlCount);
                compatibilityStats.put("totalValidSqlStatements", totalValidSqlCount);
                compatibilityStats.put("compatibleSql", totalCompatibleCount);
                compatibilityStats.put("incompatibleSql", totalIncompatibleCount);
                compatibilityStats.put("errorSql", totalErrorCount);

                double overallCompatibility = totalValidSqlCount > 0 ?
                    ((double) totalCompatibleCount / totalValidSqlCount) * 100 : 100.0;
                compatibilityStats.put("overallCompatibilityPercentage",
                    Math.round(overallCompatibility * 100.0) / 100.0);

                response.put("compatibilityStatistics", compatibilityStats);
            }

            // 详细文件结果
            response.put("fileResults", fileResults);

            // 失败文件列表
            if (!failedFiles.isEmpty()) {
                response.put("failedFiles", failedFiles);
            }

            // 生成汇总信息
            String summary = String.format(
                "目录 %s ifp框架兼容性分析完成：扫描了 %d 个XML文件，成功分析 %d 个，失败 %d 个。" +
                "总计SQL语句 %d 条，有效SQL %d 条，兼容 %d 条，不兼容 %d 条，错误 %d 条。",
                directoryPath, xmlFiles.size(), fileResults.size(), failedFiles.size(),
                totalSqlCount, totalValidSqlCount, totalCompatibleCount,
                totalIncompatibleCount, totalErrorCount
            );
            response.put("summary", summary);

            String result = objectMapper.writeValueAsString(response);
            log.info("目录ifp框架XML兼容性分析完成: {}", directoryPath);
            return result;

        } catch (Exception e) {
            log.error("目录ifp框架XML兼容性分析失败: {}", directoryPath, e);
            return mybatisXMLParser.buildDirectoryAnalysisErrorResponse(directoryPath, recursive, startTime,
                    "ifp框架目录分析过程中发生异常: " + e.getMessage());
        }
    }

}
